/*===============================================
*   文件名称：ohd_server.c
*   创 建 者：     
*   创建日期：2024年08月30日
*   描    述：
================================================*/
#include "head.h"

void upload(int connfd);
bool cmpsize(char * filename,unsigned long int filesize);
void showdir(int connfd);
void download(int connfd);

void download(int connfd)
{
    char filename[256];
    if(read(connfd,filename,sizeof(filename))<0)
        perror("filename read");
    printf("客户端输入文件名:%s\n",filename);
    DIR* dirp = opendir(".");
    if(dirp == NULL)
    {
        perror("server opendir");
    }
    struct dirent* filp = NULL;
    char send;
    while(1)
    {
        filp = readdir(dirp);
        if(filp == NULL)
        {
            send = 'f';
            write(connfd,&send,sizeof(send));
            printf("文件名错误，没有此文件!\n");
            closedir(dirp);
            return;
        }
        if(strcmp(filename,filp->d_name)==0)
        {
            send = 's';
            write(connfd,&send,sizeof(send));
            struct stat statbuf;
            if(stat(filename,&statbuf)<0)
            {
                perror("stat");
            }
            unsigned long int filesize = statbuf.st_size;
            printf("download file: %s size:%lu\n",filename,filesize);
            write(connfd,&filesize,sizeof(filesize));
            printf("开始传输文件!\n");
            int fd = open(filename,O_RDONLY);
            int buf[101];
            while(1)
            {
                int ret = read(fd,buf,sizeof(buf)-1);
                if(ret < 0)
                    perror("download read");
                if(ret == 0)
                    break;
                write(connfd,buf,ret);
            }
            close(fd);
            closedir(dirp);
            printf("文件传输完毕!\n");
            return;
        }
    }
}

void showdir(int connfd)
{
    DIR* dirp = opendir(".");
    if(dirp == NULL)
    {
        perror("server opendir");
    }
    struct dirent* filp = NULL;
    char filename[256];
    while(1)
    {
        filp = readdir(dirp);
        if(filp == NULL)
        {
            printf("read the end!\n");
            break;
        }

        strcpy(filename,filp->d_name);
        struct stat statbuf;
        if(stat(filename,&statbuf)<0)
        {
            perror("stat");
        }
        if(filename[0] == '.'|| strcmp(filename,"ohd_server.c") == 0
           ||strcmp(filename,"ohd_server")==0
           ||strcmp(filename,"head.h")==0
           ||S_ISREG(statbuf.st_mode)==0)
            continue;
        write(connfd,filename,sizeof(filename));
    }
    strcpy(filename,"end");
    write(connfd,filename,sizeof(filename));
    closedir(dirp);
    printf("服务器文件目录传输完成!\n");
}

bool cmpsize(char * filename,unsigned long int filesize)
{
    struct stat statbuf;
    if(stat(filename,&statbuf)<0)
    {
        perror("cmpsize stat");
        return false;
    }
    return statbuf.st_size == filesize;
}

void upload(int connfd)
{
    int order; 
    unsigned long int filesize;
    int ret;
    char filename[256]; 
start:
    while(1)
    {
        if(read(connfd,&order,sizeof(order))<0)
        {
            perror("upload order read");
        }
        else
        {
            switch(order)
            {
                case 1:
                    printf("开始传输网盘目录!\n");
                    showdir(connfd);
                    break;
                case 2:
                    printf("开始上传!\n");
                    goto begin;
                    break;
                case 0:
                    printf("退出上传模式!\n");
                    return;
            }
        }
    }
begin:
    ret = 0;
    while(ret <= 0)
    {
        ret = read(connfd,&filesize,sizeof(filesize));
    }
    printf("成功接收文件大小，为：%lu\n",filesize);
    //memset(filename,'\0',sizeof(filename));
    ret = 0;
    while(ret <= 0)
    {
        ret = read(connfd,filename,sizeof(filename));
    }
    printf("成功接收文件名，为：%s\n",filename);
    int send = 0;
    char end = 'e';
    while(send<=0)
    {
        send = write(connfd,&end,sizeof(end));
    }
    int fd = open(filename,O_WRONLY|O_TRUNC|O_CREAT,0664);
    if(fd < 0)
    {
        perror("open");
        printf("服务器打开/创建文件失败!\n");
    }
    printf("开始读取文件数据!\n");
    char buf[101];
    while(!cmpsize(filename,filesize))
    {
            ret = read(connfd,buf,sizeof(buf)-1);
            write(fd,buf,ret);
                //char end = 'e';
    }
    printf("文件写入完成!\n");
    send = 0;
    while(send<=0)
    {
        send = write(connfd,&end,sizeof(end));
    }
    close(fd);
    goto start;
}

int main(int argc, char *argv[])
{ 
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd < 0)
    {
        perror("socket");
        return -1;
    }
    printf("sock success!\n");
    struct sockaddr_in srvaddr;
    memset(&srvaddr, 0, sizeof(srvaddr)); //清空结构体
    srvaddr.sin_family = AF_INET; //地址族IPv4
    srvaddr.sin_port = htons(5500); //端口号
    srvaddr.sin_addr.s_addr = inet_addr("192.168.79.130"); //本机IP地址
    if(bind(sockfd, (struct sockaddr*)&srvaddr, sizeof(srvaddr))<0)
    {
        perror("bind");
        return -1;
    }
    printf("bind success!\n");
    
    if(listen(sockfd,5)<0)
    {
        perror("listen");
        return -1;
    }
    printf("listen success!\n");
    int connfd;
loop:
    connfd = accept(sockfd,NULL,NULL);
    if(connfd<0)
    {
        perror("accept");
        return -1;
    }
    printf("accept success!\n");
    int order;
    while(1)
    {
        if(read(connfd,&order,sizeof(int))<0)
        {
            printf("信息接收失败!\n");
            perror("order read");
        }
        else
        {
            switch(order)
            {
                case 1://upload
                    printf("进入上传模式!\n");
            	    upload(connfd);
                    break;
                case 2://download
                    printf("进入下载模式!\n");
                    download(connfd);
                    break;
                case 3:
                    showdir(connfd);
                    break;
                case 0://quit one connect
                    //close(sockfd);
                    close(connfd);
                    printf("客户端断开连接!\n");
                    goto loop;
                default:
                    printf("无输入\n");
                    break;
            }
        }
    }
    return 0;
} 
